package com.secsbrain.engine.web.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSON;
import com.secsbrain.engine.biz.constant.EnumDefinition;
import com.secsbrain.engine.biz.constant.ProcessParamConstant;
import org.activiti.engine.HistoryService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.secsbrain.common.ErrorCodeEnum;
import com.secsbrain.common.ResponseVo;
import com.secsbrain.engine.client.iface.ProcessService;
import com.secsbrain.engine.client.model.AbandonProcessParam;
import com.secsbrain.engine.client.model.ProcessDeal;
import com.secsbrain.engine.client.model.ProcessDto;
import com.secsbrain.engine.client.model.StartProcessParam;
import com.secsbrain.engine.client.model.SubmitRequest;

/**
 * 流程相关控制层
 *
 * @author zhaoyi
 */
@RestController
@EnableEurekaClient
public class FlowController implements ProcessService{
	
    private static final Logger logger = LoggerFactory.getLogger(FlowController.class);

	@Autowired
	private RepositoryService repositoryService;
	
	@Autowired
	private TaskService taskService;
	
	@Autowired
	private RuntimeService runtimeService;
	
	@Autowired
	private HistoryService historyService;
    
    /**
     * 功能描述: <br>
     * 开始流程
     *
     */
    @SuppressWarnings("unchecked")
    public ResponseVo<ProcessDto> startProcess(@RequestBody StartProcessParam startProcessParam) {
        Assert.hasText(startProcessParam.getProcessDefinitionKey(), "流程定义key不能为空");
        Assert.hasText(startProcessParam.getStartUserId(), "启动用户ID不能为空");
    	
    	logger.debug("开始流程...{}", JSON.toJSONString(startProcessParam));
    	
    	List<ProcessDefinition> processDefinition=repositoryService.createProcessDefinitionQuery()
    		.processDefinitionKey(startProcessParam.getProcessDefinitionKey()).list();
    	if(processDefinition==null){
    		return ErrorCodeEnum.ERROR_COMMON_CHECK.getResponseVo("流程定义key不存在");
    	}
    	
    	ProcessEngine processEngine=ProcessEngines.getDefaultProcessEngine();
    	//设置启动用户
    	processEngine.getIdentityService().setAuthenticatedUserId(startProcessParam.getStartUserId());
    	
    	// 分配任务的人员
        Map<String, Object> vars = new HashMap<String, Object>();
        vars.put(ProcessParamConstant.ASSIGNEE, StringUtils.isEmpty(startProcessParam.getAssignee())?
        		startProcessParam.getStartUserId():startProcessParam.getAssignee());
    	
    	// 启动流程
    	ProcessInstance processInstance=runtimeService
    			.startProcessInstanceByKey(startProcessParam.getProcessDefinitionKey(),vars);
    	
    	ProcessDto processDto=new ProcessDto();
    	processDto.setProcessInstanceId(processInstance.getId());
    	processDto.setStartUserId(processInstance.getStartUserId());
    	processDto.setProcessDefinitionKey(processInstance.getProcessDefinitionKey());
    	
    	logger.debug("开始流程成功！返回：{}",JSON.toJSONString(processDto));
    	return ResponseVo.getSuccessResponse(processDto);
    }
    
    /**
     * 功能描述: <br>
     * 废弃流程
     *
     * @param abandonProcessParam
     * @return
     */
    @SuppressWarnings("unchecked")
    public ResponseVo<String> abandon(@RequestBody AbandonProcessParam abandonProcessParam){
        String processInstanceId=abandonProcessParam.getProcessInstanceId();
    	Assert.hasText(abandonProcessParam.getStartUserId(), "启动用户ID不能为空");
        Assert.hasText(processInstanceId, "流程实例ID不能为空");
    	
    	logger.debug("废弃流程...{}",JSON.toJSONString(abandonProcessParam));

    	HistoricProcessInstance historicProcessInstance=historyService.createHistoricProcessInstanceQuery()
    		.processInstanceId(processInstanceId).singleResult();
    	if(historicProcessInstance==null){
    		return ErrorCodeEnum.ERROR_COMMON_CHECK.getResponseVo("流程不存在");
    	}
    	
    	if(!abandonProcessParam.getStartUserId().equals(historicProcessInstance.getStartUserId())){
    		return ErrorCodeEnum.ERROR_COMMON_CHECK.getResponseVo("废弃流程的用户必须是启动用户");
    	}
    	
    	Task task=taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
    	if(task==null){
    		return ErrorCodeEnum.ERROR_COMMON_CHECK.getResponseVo("流程已结束");
    	}
    	
    	Map<String,Object> agreeMap = new HashMap<>();
    	agreeMap.put("agree", EnumDefinition.ApprovalStatus.ABANDON.getCode());
    	
     	taskService.complete(task.getId(),agreeMap);
     	
    	logger.debug("废弃流程成功！");
    	return ResponseVo.getSuccessResponse(processInstanceId);
    }
    
    /**
     * 功能描述: <br>
     * 通过任务
     *
     * @return
     */
    @SuppressWarnings("unchecked")
    public ResponseVo<String> pass(@RequestBody ProcessDeal processDeal){
    	Assert.hasText(processDeal.getProcessInstanceId(), "流程实例ID不能为空");
        Assert.hasText(processDeal.getRoleCode(), "角色编号不能为空");
        Assert.hasText(processDeal.getUserId(), "用户ID不能为空");
        
    	Task task=taskService.createTaskQuery()
    			.taskAssignee(processDeal.getRoleCode()).processInstanceId(processDeal.getProcessInstanceId()).singleResult();
    	if(task==null){
    		task=taskService.createTaskQuery()
        			.taskAssignee(processDeal.getUserId()).processInstanceId(processDeal.getProcessInstanceId()).singleResult();
    	}
    	
    	if(task==null){
    		return ErrorCodeEnum.ERROR_COMMON_CHECK.getResponseVo("流程不存在或办理人不正确");
    	}
    	
    	Map<String,Object> vars = new HashMap<>();
    	vars.put("agree", EnumDefinition.ApprovalStatus.AGREE.getCode());
    	taskService.complete(task.getId(),vars);
    	
    	logger.debug("通过任务成功！");
     	return ResponseVo.getSuccessResponse(processDeal.getProcessInstanceId());
    }
    
    /**
     * 功能描述: <br>
     * 打回任务
     *
     * @param processDeal
     * @return
     */
    @SuppressWarnings("unchecked")
    public ResponseVo<String> refuse(@RequestBody ProcessDeal processDeal){
    	Assert.hasText(processDeal.getProcessInstanceId(), "流程实例ID不能为空");
        Assert.hasText(processDeal.getRoleCode(), "角色编号不能为空");
        Assert.hasText(processDeal.getUserId(), "用户ID不能为空");
        
    	Task task=taskService.createTaskQuery()
    			.taskAssignee(processDeal.getRoleCode()).processInstanceId(processDeal.getProcessInstanceId()).singleResult();
    	if(task==null){
    		task=taskService.createTaskQuery()
        			.taskAssignee(processDeal.getUserId()).processInstanceId(processDeal.getProcessInstanceId()).singleResult();
    	}
    	
    	if(task==null){
    		return ErrorCodeEnum.ERROR_COMMON_CHECK.getResponseVo("流程不存在或办理人不正确");
    	}
    	
    	HistoricProcessInstance historicProcessInstance=historyService.createHistoricProcessInstanceQuery()
        		.processInstanceId(task.getProcessInstanceId()).singleResult();
    	
		Map<String, Object> vars = new HashMap<String, Object>();
        vars.put("assignee", historicProcessInstance.getStartUserId());//默认打回给发起人
        vars.put("category", EnumDefinition.ApprovalStatus.REFUSE.getCode()+"");
        vars.put("agree", EnumDefinition.ApprovalStatus.REFUSE.getCode());
    	taskService.complete(task.getId(),vars);
    	
    	logger.debug("打回任务成功！");

    	return ResponseVo.getSuccessResponse(processDeal.getProcessInstanceId());
    }
    
    /**
     * 功能描述: <br>
     * 提交申请
     *
     * @param processInstanceId  流程实例ID
     * @param userId  申请人ID
     * @return
     */
    @SuppressWarnings("unchecked")
    public ResponseVo<String> submitRequest(@RequestBody SubmitRequest submitRequest){
        Assert.hasText(submitRequest.getProcessInstanceId(), "流程实例ID不能为空");
        Assert.hasText(submitRequest.getUserId(), "申请人ID不能为空");
        Assert.hasText(submitRequest.getAssignee(), "审批人不能为空");
        
    	logger.debug("开始提交申请...{}",JSON.toJSONString(submitRequest));
    	
    	Task task=taskService.createTaskQuery().taskAssignee(submitRequest.getUserId())
    			.processInstanceId(submitRequest.getProcessInstanceId()).singleResult();
    	if(task==null){
    		return ErrorCodeEnum.ERROR_COMMON_CHECK.getResponseVo("流程不存在或办理人不正确");
    	}
    	
		Map<String, Object> vars = new HashMap<String, Object>();
        vars.put("agree", EnumDefinition.ApprovalStatus.AGREE.getCode());
        vars.put("assignee", submitRequest.getAssignee());

    	taskService.complete(task.getId(),vars);
    	
    	logger.debug("提交申请成功！");
    	
    	return ResponseVo.getSuccessResponse(submitRequest.getProcessInstanceId());
    }

}
